package com.codedef.config;

import com.codedef.common.exception.CustomException;
import com.codedef.common.response.ResultCode;
import com.codedef.util.CheckPath;
import com.codedef.util.JwtUtil;
import com.codedef.util.UriParseUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

//实现用户权限校验
@Slf4j
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {

    //令牌头名字（可能存在头文件里，或cookie里，或请求体里	）
    private static final String AUTHORIZE_TOKEN = "Authorization";

    @Autowired
    CheckPath checkPath;

    /**
     * 全局过滤器
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取Request、Response对象
        ServerHttpRequest request = exchange.getRequest();
//        ServerHttpResponse response = exchange.getResponse();

        //获取请求的URI
        String path = request.getURI().getPath();

        // 如果是登录、goods等开放的微服务[这里的goods部分开放],则直接放行,这里不做完整演示，完整演示需要设计一套权限系统
        // 读配置文件中需要拦截的接口，其他接口全部放行
//        if (path.startsWith("/user/login")) {
//            //放行
//            Mono<Void> filter = chain.filter(exchange);
//            return filter;
//        }
        if (!UriParseUtil.needToIntercept(checkPath.root, path)) {
            // 放行
            Mono<Void> filter = chain.filter(exchange);
            log.info("该请求放行");
            return filter;
        }

        /*  --------------------------- 验证Token --------------------------- */
        log.info("该请求拦截 ※");
        //获取头文件中的令牌信息
        String token = request.getHeaders().getFirst(AUTHORIZE_TOKEN);

        //如果头文件中没有令牌信息，则从请求参数中获取
        if (token == null || "".equals(token)) {
            token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
        }
        //如果请求参数中没有令牌信息，则从cookie中获取
        if (token == null || "".equals(token)) {
            HttpCookie httpCookie= request.getCookies().getFirst(AUTHORIZE_TOKEN);
            if(httpCookie!=null){
                token = httpCookie.getValue();
            }
        }

//        System.out.println("Token is " + token);

        // 如果令牌为空，则输出错误代码
        if (StringUtils.isEmpty(token)) {
            //设置方法不允许被访问，405错误代码
//            response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED);
//            return response.setComplete();
            System.out.println("令牌为空");
//            response.setStatusCode(HttpStatus.NOT_FOUND);
            throw new CustomException(ResultCode.USER_NOT_LOGGED_IN);

        }

        //解析令牌数据
        Claims claims = JwtUtil.parseJWT( token.substring("Bearer ".length()) );
        Integer userId = (Integer) claims.get("USER_ID");

        // Token验证通过后 在请求头中添加UserId
        ServerHttpRequest newRequest = request.mutate().header("USER_ID", String.valueOf(userId)).build();
        // 将现在Request转化为Change对象
        ServerWebExchange newBuild = exchange.mutate().request(newRequest).build();

        //放行
        return chain.filter(newBuild);
    }


    /**
     * 过滤器执行顺序（越小越先执行）
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
